home *** CD-ROM | disk | FTP | other *** search
- MAKEBIN V1.0
- 16 April 1989
- by Michael Day
-
- At first glance it would seem to be a rather pointless
- effort to create a program that converts an EXE file to a BIN
- file format. After all, the DOS utility EXE2BIN already provides
- that capability. Closer inspection will show however that the DOS
- utility EXE2BIN does not convert an EXE style program file to a
- BIN file, but rather it converts a transitional EXE file into the
- BIN format that it is intended to be in.
-
- If you wish to convert a normal EXE program file into a BIN
- file, the usual response you will get is that it is impossible.
- As MAKEBIN shows, that's not entirely true. MAKEBIN can convert a
- normal EXE program file into a BIN file. There are however a few
- limitations that are placed on the conversion.
-
- The primary limitation is that the size of the EXE program
- must be less than 64K. This is not a direct limitation of
- MAKEBIN, but rather one that most loaders place on the BIN file
- size because they don't know how to load a binary image larger
- than 64K.
-
- Another limitation is that you cannot allocate, change or
- de-allocate DOS memory within the BIN program. There are two
- reasons behind this, one is because many programs that allocate
- memory rely on DOS to de-allocate the memory. When a MAKEBIN
- program is exited, it does not return through DOS, so the memory
- is not de-allocated, which would leave the DOS memory fragmented.
- The other reason is that most loaders pre-allocate memory for the
- BIN file, and do not take kindly to having memory yanked out from
- under them. It is usually assumed by the loader that the BIN
- program will only use the program space initially given it by the
- loader.
-
- The amount of memory needed for a program cannot be readily
- determined for a standard BIN file because there is no specific
- field in the file that indicates how much memory it will require.
- There are usually two mechanisms used to handle this. One is to
- demand that the programmer specify the space that the program is
- to be loaded into. Another common method found in most database
- programs is to simply look at the size of the BIN file and
- allocate that much memory for the program. This works for most
- binary image files, but EXE files allocate additional memory for
- themselves beyond the actual program size when they are loaded.
-
- Since MAKEBIN was targeted for use with database programs, the
- memory allocation problem was solved by re-sizing the EXE program
- while it is being converted to a BIN file. The size of the BIN
- file is made to be equal to (actually slightly greater than) the
- amount of memory the program needs. This places a limitation on
- the total memory usage of the EXE program to be less than 64K
- since that is the maximum file size that can be loaded.
-
- Why use MAKEBIN?
-
- One reason is to be able to create a BIN program from a
- program that cannot normally create one such as Turbo Pascal
- V5.0. If you are used to programming in Turbo Pascal, but need to
- create a BIN file (such as for use with Dbase III), MAKEBIN might
- be the answer for you.
-
-
- Why convert a perfectly good EXE file to a BIN file?
-
- Since Dbase III normally allows you to run an EXE program
- with its RUN command, at first blush it would seem to be a
- pointless effort to go to all that extra effort to convert the
- program to a BIN file just to be able to run it with the
- LOAD/CALL commands. There is a reason for the madness though.
-
- A problem with the RUN command is that the program must be
- loaded from disk each time. This means that you must wait for the
- program to be loaded each time you call it. For simple activities
- this may be an unacceptable delay. This is particularly true if
- the program must be closely tied to input or output activities.
-
- When a program is loaded with the LOAD command, it stays in
- memory ready for immediate use with the CALL command. The only
- time you have to wait for the load from disk is when you use the
- LOAD command to initially load the program into memory.
-
-
- Creating programs for use with MAKEBIN
-
- MAKEBIN was targeted for use with Turbo Pascal V5.0 and
- Database programs like Dbase III. As such, I will be discussing
- issues that are specific to Turbo Pascal and the database
- programs. However, there is no inherent limitation to prevent you
- from using any EXE based program with MAKEBIN as long as it meets
- the limitations presented.
-
- While the issues I will cover are specific to Turbo Pascal,
- they are applicable to other compiler/assemblers as well. There
- may be other issues that I have not anticipated or that might be
- applicable to another compiler that I haven't discussed.
-
- The limitations and requirements that I discuss here should
- not be construed to be the only ones involved. It should be
- realized that MAKEBIN is operating the EXE program in a condition
- that is abnormal to its standard operating environment. As a
- result, there may be any number of issues that will affect the
- operation of the program that would not be a problem under normal
- conditions.
-
-
- Standard EXE2BIN:
-
- By far, the easiest application of MAKEBIN is to simply
- convert an existing operational EXE program to a BIN file. No
- other activity needs to be performed other than using MAKEBIN to
- convert the file and using the LOAD/CALL commands in the database
- program to run it rather than using the RUN command.
-
- Re-entrancy:
-
- There are limitations to converting a standard EXE file to a
- BIN file. The primary problem is when the program is re-entered
- after the first call. Since the program remains in memory, any
- typed constant variables will be in the state they were in when
- the program was exited from the last CALL. This could also be a
- problem if the program uses self-modifying code. The point being
- if the program expects things to be in a specific condition as a
- result of the initial load when it is run, you may experience
- problems since on the second CALL they may no longer be in that
- condition.
-
- While Turbo Pascal itself does not have specific limitations
- of re-starting a program that resides in memory, the program
- written may quite possibly have typed constants or self modifying
- code in it that fall under this category of being a problem.
-
- On the other hand, you can use this side effect to control
- successive CALLs to the program. Since the program is not
- reloaded the typed constant will not be changed when the program
- is re-entered.
-
-
- Memory allocation:
-
- Since a BIN file will generally be loaded under another
- program, MAKEBIN will allocate the minimum amount of memory
- possible for the program. In a Turbo Pascal program this is a
- combination of the program size, the data size, the stack size,
- and the minimum heap size specified. These are controlled by the
- $M compiler directive. Since the BIN file must be limited to less
- than 64K in size, the combination of the various sizes must not
- exceed the 64K size limit.
-
- A BIN program created by MAKEBIN will not allow the program
- to allocate additional memory space beyond that initially defined
- by the program. Normally in a Turbo Pascal program this is not a
- problem. In special cases, or in programs generated by other
- compilers it may be a problem.
-
- If an attempt is made to allocate more memory than that
- allocated initially to the program, an error will be returned
- indicating that there is no more memory available to be
- allocated.
-
- Another possible problem area is if the program attempts to
- change it's own memory allocation size. Again, an error will be
- returned if this is attempted. Normally this is not a problem in
- a Turbo Pascal program, though it may occur if the program
- attempts to EXEC to DOS as it tries to free excess memory for use
- by the shelled program. Since you cannot change the allocated
- memory, this will result in an error condition being returned.
-
-
- Inter-Process Communications:
-
- Normally, a BIN program communicates with it's calling
- program via register variables. MAKEBIN provides for this
- communications with an interface record that contains the
- register values that existed upon entry to the BIN program, and
- which will be passed back to the calling program on exit from the
- BIN program. Normally these register values should not be changed
- unless explictly specified to do so by the calling program.
-
- The Inter-Process Communications area can be accessed by
- referencing the pointer found at PspSeg-2. (A pointer which is
- located two paragraphs, 32 bytes, below the BIN program's own PSP
- segment.) The IPC pointer points to the record which contains the
- register values.
-
- For database programs the registers DS:BX generally point to
- a variable that is passed to the BIN program. Thus by creating a
- pointer out of the values found in registers DS:BX you can
- reference the database variable. Usually this is a character
- string, but it can be any of the allowed database memory
- variables. The demo programs provided show how to access the
- database string variable.
-
- Redirect of BIN entry:
-
- The BIN program must be entered normally the first time so
- that it can be loaded and initialized. Once initialized though,
- you do not have to go through the entire initialization sequence
- again. Doing so can slow down the performance of the BIN program
- slightly since it has to go through the entire initialization
- sequence each time it is called.
-
- Redirecting the entry point allows the BIN program to act
- similar to a TSR. In fact, much of the issues and requirements
- involved are the same as with a TSR.
-
- To change the entry point, simply call the SetBinEntry
- procedure at some point in the program. I recommend that it be
- placed near the end of the program. Like a TSR, you need to keep
- the Turbo program active for the functions to work. This means
- that you must exit the program with the "Keep" procedure.
-
- Since Turbo Pascal programs also take over a number of
- interrupt vectors while it is in operation, you must also restore
- the old vectors before returning to the calling database program.
- You can use the "SwapVectors" procedure to perform this. I
- recommend that you place all three calls at the end of the
- program so that they won't get lost.
-
- Example:
-
- begin
- DoProgram...
-
- SetBinEntry(MyProc);
- SwapVectors;
- Keep(0);
- end.
-
-
- You may want to continue to use the Turbo Pascal Error
- handler when you re-enter the program. If this is the case, you
- must use the SwapVectors procedure to restore the Turbo Pascal
- vectors at the beginning of the re-entry into the BIN program,
- and again at the exit.
-
- Example:
-
- {$F+}
- procedure MyProc;
- begin
- SwapVectors;
-
- Dosomething....
-
- SwapVectors;
- end.
-
- Additionally, if you are using other functions within turbo
- that require the use of the original interrupt vectors, such as
- the 80x87 emulation routines, You *must* use the SwapVectors
- procedure or strange things will happen. If you are in doubt,
- then use the SwapVectors procedure.
-
- You should *never* call a re-entrancy procedure directly
- from the main BIN program (the part that is run the first time).
- This is particularly true if you are swapping the vectors. The
- SwapVectors is a toggle. It swaps the old vectors with an
- internal table. Thus if you were to call the re-entrancy
- procedure you would be swapping the old vectors back in losing
- the ones you really want.
-
- Also note that the re-entered procedure has been declared as
- FAR. You must *always* declare the re-entry procedure as FAR.
- This is one area where the BIN program differs from a TSR. With a
- TSR you would declare the re-entry procedure as an "Interrupt;"
- procedure.
-
- ** DO NOT ** declare the re-entry procedure as an interrupt
- procedure. It may appear to work, but when the procedure
- terminates the BIN program's stack will become corrupted.
-
- The stack corruption is caused because an Interrupt
- procedure has one additional word on the stack that contains the
- flags prior to calling the interrupt procedure. Declaring the
- procedure as an interrupt will cause the procedure to try to pop
- the additional word from the stack. Since the BIN loader calls
- the procedure as a normal FAR procedure it will not have placed
- the additional word on the stack. This causes the stack to
- continually shrink until it wraps around into code or data space
- disrupting the program.
-
-
- Demo programs:
-
- The Demo programs provided show how to create Turbo Pascal
- programs which can be converted to BIN files for use with a
- database program.
-
- The first one is called BinDemo1. It consists of the files
- BinDemo1.Bin, BinDemo1.Prg, and BinDemo1.Pas (BinDemo1.Pas is the
- source to BinDemo1.Bin). BinDemo1 is a simple example of a BIN
- program that was created by Turbo Pascal to run under a database
- program. It uses an internal counter to keep track of each time
- it is entered. The program can accept a string variable from the
- database program, and return a modified string back to the
- program. To run BinDemo1, just load Dbase or one of the clones,
- and enter the command "DO BINDEMO1".
-
- As an alternative, you can use the BinRun program which
- simulates a database environment to run a BIN file. BinRun has
- the added advantage that you can run it under Turbo Debugger so
- that you can use it to debug the BIN program. To run the program
- with BinRun, just enter "BINRUN BINDEMO1" at the DOS prompt. To
- run it under the Turbo Debugger enter "TD BINRUN BINDEMO1".
-
- Note: The Turbo Debugger does not know how to access the source
- and map tables for the BIN program because they aren't included
- in the EXE of the BinRun program, therefore you will only be able
- to see the BIN program code in the CPU mode.
-
- The other demo program is called BinDemo2, and includes the
- files BinDemo2.Prg, BinDemo2.Bin, and BinDemo2.PAS. BinDemo2 is
- similar to BinDemo1, except that it shows how to redirect the
- entry point into the BIN program from the DataBase program.
-
-
- Programs and files on the disk:
-
- MAKEBIN.DOC This documentation file
-
- MAKEBIN.ASM ASM Source for MAKEBIN
- MAKEBIN.PAS Pascal Source for MAKEBIN
- MAKEBIN.EXE The program to make a BIN file
-
- IPCUNIT.PAS Pascal Source for a BIN interface
-
- BINDEMO1.BIN Demo1 BIN program file
- BINDEMO1.PRG Demo1 database PRG file
- BINDEMO1.PAS Demo1 Pascal Source
-
- BINDEMO2.BIN Demo2 BIN program file
- BINDEMO2.PRG Demo2 database PRG file
- BINDEMO2.PAS Demo2 Pascal Source
-
- BINRUN.PAS Pascal Source for BINRUN
- BINRUN.EXE The program to simulate a database environment
-
- MAKEHEX.PAS Utility used to convert an assembler hex file
- MAKEHEX.EXE to a hex format acceptable for Turbo Pascal
-
- Using MAKEBIN:
-
- To use MAKEBIN, just create your program using Turbo Pascal
- as you normally would, compile it to an EXE file, then run the
- MAKEBIN program to convert it to a BIN file. That's all there is
- to it. Couldn't be simpler right?
-
-
- How does it work?
-
- A BIN file normally starts with a code offset of zero, and
- is a simple memory image of the code to be run. This is very
- similar to a COM file except that there is no PSP or other system
- hooks to worry about, just a simple memory image of the program
- segment.
-
- An EXE file on the other hand is a complex program file
- which requires hooks to the operating system (the PSP), and
- special treatment to prepare the program contained in the file
- before it is run. This requires that an EXE be provided a
- "loader" so that it can be properly converted.
-
- MakeBin builds a loader onto the front of the EXE program so
- that it can be "Loaded" the first time it is called. A flag is
- then set indicating that it has been loaded so that that portion
- of the loader will be bypassed on successive calls to the BIN
- program.
-
- The Loader converts the special memory image of the EXE file
- into the relocated memory image required to run the program. This
- must be done at load time since it is not known where in memory
- the program will reside until it has been loaded at run time.
-
- MakeBin also attaches a dummy PSP to the beginning of the
- program. This PSP is a copy of the database program's PSP. Unlike
- an EXEC'd program which gets a "child" PSP all its own, the
- MakeBin created PSP is a replicate of the database PSP. It has
- direct access to several of the database's PSP hooks. These
- include the database's environment pointer, and it's handle
- table.
-
- The reason why a replicate PSP is used rather than a
- separate child PSP is because normally a BIN program does not
- have it's own PSP, therefore it uses the database program's PSP
- if it needs access to one. EXE type programs however normally
- expect to have their own PSP to work with. This can cause
- conflicts as the EXE program may try to modify what it thinks is
- its own PSP. Such an action can disrupt the PSP for the database,
- so a mechanism was need to isolate the PSP for the BIN file while
- still allowing it to think that it had access to the database
- PSP. Replicating the database PSP was the answer.
-
- Replicating the PSP also allows one other aspect of the PSP
- to be handled. The memory size block must be set to what the BIN
- program will expect to see. By using the replicate PSP we can
- change this without affecting the database PSP. It also lets the
- BIN program change the return vectors in the PSP without
- adversely affecting the database PSP.
-
- Normally a well behaved program will keep track of it's PSP
- segment by saving the segment location feed to it in the ES
- segment register when the program is run. Some less well behaved
- programs though expect the PSP to be immediately in front of the
- program itself. This is normally true, but not always so. By
- creating our own PSP, we can place it immediately below the
- program so that even an ill-behaved program won't get upset.
-
- Another area of concern, though much less so than the PSP,
- is the MCB. Very few programs make use of the MCB, but some do.
- Once again, a well behaved program would not present a problem
- since it would use the DOS function to get the base MCB and then
- search through the chain for its own MCB. An ill-behaved program
- though may expect to find its MCB immediately below the PSP. As
- such, MAKEBIN creates a dummy MCB immediately below the PSP to
- keep the ill-behaved program happy. The dummy MCB is created to
- appear to be the BIN program's MCB, and is the last MCB in the
- chain. This is a dummy MCB however, and it does not really appear
- in the MCB chain. It can only be found by an ill behaved program
- that assumes the MCB to be immediately below the PSP.
-
- Since the BIN program often has to communicate with the
- database program, one additional paragraph has been allocated
- just below the dummy MCB. The first location of this paragraph is
- the only one that is used. It contains a pointer to a table in
- memory of the register values that were saved upon entry to the
- BIN program from the database program. From Turbo Pascal this
- table can be accessed by referring to "PspSeg-2".
-
- Using the IPC unit:
-
- To make many of these programming issues easier for you, the
- unit "IpcUnit" was created to provide the various parameters and
- functions needed. Simply include it in your Uses statement at the
- beginning of your program. It does not require that it be in any
- special order with respect to other units, other then any
- possible dependency that the other units might have on the
- IpcUnit.
-
- MAKEBIN.PAS is the source file to MAKEBIN.EXE. It's main
- purpose is to append the custom loader onto the front of the EXE
- file (the large HEX table in the file) and to adjust the size of
- the file to be the desired size for a BIN file (equal to or
- larger than the total memory area used by the program). The
- MAKEBIN program also assists in the filename creation by adding
- the required EXE and BIN file extensions to the names. If a
- second filename parameter is not given, then the BIN file is
- assumed to have the same name as the EXE file.
-
- MAKEBIN.ASM is the assembler source to the hex table in the
- MAKEBIN.PAS program. It is written for the Seattle Assembler. I
- use the Seattle Assembler because it is fast and generates hex
- files directly. Unfortunately, the hex file generated by the the
- assembler is not exactly in the form needed to incorporate it
- directly into the Pascal program. Thus the existence of MAKEHEX,
- which converts the Intel format hex file produced by the
- assembler into the form needed to insert it into the typed
- constant array used in MAKEBIN.
-
- MS-DOS is a registered trademark of MicroSoft Corp.
- Dbase is a registered tradmark of Aston-Tate.
- Seattle Assmebler is produced by Seattle Computer Products
- MakeBin belongs to me, Michael Day. So there! Nah!
-
- <eof>